from sklearn import datasets
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

# 数据集 150条样本
x_data = datasets.load_iris().data
y_data = datasets.load_iris().target

print(x_data)

# # 使用相同的seed 使得输入特征/标签一一对应
# np.random.seed(116)
# np.random.shuffle(x_data)
# np.random.seed(116)
# np.random.shuffle(y_data)
# tf.random.shuffle(116)
#
# # 取数据分为用不相见的训练集和测试集
# x_train = x_data[:-30]
# y_train = y_data[:-30]
# x_test = x_data[-30:]
# y_test = y_data[-30:]
#
# # 进行数据转换 否则后面矩阵相乘的时候会因为数据类型不一致报错
# x_train = tf.cast(x_train, tf.float32)
# x_test = tf.cast(x_test, tf.float32)
#
# # 将数据集打包为特征-标签一一对应 , 把数据集分批次,每个批次batch组数据
# train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
# test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
#
# # 生成神经网络的参数 ,4个输入特征,输入层为4个输入节点,因为三分类,故输出层为三个神经元
# # 哦那个tfVariable()标记参数可训练
# # 使用seed使每次生成的随机数相同(方便教学,使大家结果都一致,在先是使用时不写seed)
# w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))
# b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))
#
# lr = 0.1  # 学习率
# train_loss_results = []  # 将每轮的loss记录再此列表中 为后续画loss曲线提供数据
# test_acc = []  # 将每轮的acc记录在此列表中,为后续画acc曲线做准备
# epoch = 500  # 循环500轮
# loss_all = 0  # 每轮分4个step.loss_all记录四个step生成loss的和
#
# for epoch in range(epoch):  # 数据集级别的循环 每个epoch循环一次数据集
#     for step, (x_train_db, y_train_db) in enumerate(train_db):  # batch级别的循环 每个step一个批次
#         with tf.GradientTape() as tape:  # with结构记录梯度信息
#             y = tf.matmul(x_train_db, w1) + b1  # 神经网络乘加运算
#             y = tf.nn.softmax(y)  # 使输出y符合概率分布
#             y_ = tf.one_hot(y_train_db, depth=3)  # 将标签值转换为独热码格式 方便计算loss和acc
#             loss = tf.reduce_mean(tf.square(y - y_))  # 采用均方差损失函数为mse=mean((y-y_)^)
#             loss_all += loss.numpy()  # 将每个step计算出的loss累加 为后续求loss平均值提供支持
#         # 计算loss对各个参数的梯度
#         grads = tape.gradient(loss, [w1, b1])
#
#         # 实现梯度更新
#         # w1 = w1 - lr * w1_grad
#         # b = b - lr * b_grad
#         w1.assign_sub(lr * grads[0])  # 参数w自更新
#         b1.assign_sub(lr * grads[1])  # 参数b自更新
#
#     # 每个epoch 打印loss信息
#     print("Epoch {},loss:{}".format(epoch, loss_all / 4))
#     train_loss_results.append(loss_all / 4)  # 将4个step的loss求平均记录在此变量中
#     loss_all = 0  # 归零 , 为记录下一个epoch的loss做准备
#
#     # 测试部分
#     total_correct, total_number = 0, 0
#     for x_test_db, y_test_db in test_db:
#         # 使用更新厚的参数进行预测
#         y = tf.matmul(x_test_db, w1) + b1
#         y = tf.nn.softmax(y)
#         pred = tf.argmax(y, axis=1)  # 返回y中最大值的索引,即预测的分类
#         # 将pred转换为y_test的数据类型
#         pred = tf.cast(pred, dtype=y_test_db.dtype)
#         # 若分类正确,则correct=1,否则为0,将bool类型转换为int型
#         correct = tf.cast(tf.equal(pred, y_test), tf.int64)
#         # 将每个batch的correct数加起来
#         correct = tf.reduce_sum(correct)
#         # 将所有batch的correct数加起来
#         total_correct += int(correct)
#         # total_number 为测试的总样本数 , 也就是x_test的行数 , shape[0]返回变量的行数
#         total_number += x_test.shape[0]
#     # 总的准确率等于totalcorrect/total_number
#     acc = total_correct / total_number
#     test_acc.append(acc)
#     print("Test acc:", acc)
#     print("-----------------------------------")
#
# # 绘制loss
# plt.title("Loss Function Curve")
# plt.xlabel("Epoch")
# plt.ylabel("Loss")
# plt.plot(train_loss_results, label="$Loss")  # 逐点患处trian_loss_resules值并连线
# plt.legend()  # 画出曲线图标
# plt.show()
# # 绘制acc
# plt.title("ACC Curve")
# plt.xlabel("Epoch")
# plt.ylabel("ACC")
# plt.plot(test_acc, label="$Accuracy$")
# plt.legend()
# plt.show()
